use anyhow::{Result, anyhow};
use bytes::{Buf, BufMut, BytesMut};

///自定义的加密+压缩 传输
/// 基于tcp协议，有状态的传输，
/// 1.连接成功
/// 2.认证
/// 3.使用预设key及加密算法加密
/// 4.压缩
/// 5.传输
/// ## 认证请求报文格式
/// |cmd|len|content|
/// |-|-|-|-|
/// |1|2|var|
/// cmd：指令类型：1个字节，取值范围：0x01（认证）,0x02(数据传输),0x11(认证结果)，0x12（数据响应），0x03(服务器连接),0x13(服务器连接结果)
/// 数据长度2个字节 最多65535个字节，63M
/// 认证内容为：guid格式
/// 数据内容为先加密压缩后的格式
///
pub struct EthanRequestProto {
    cmd: EthanCommandType,
    len: u16,
    data: Vec<u8>,
}
#[derive(Debug, Clone, Copy)]
pub enum EthanCommandType {
    Auth,
    Trans,
    AuthResult,
    TransResponse,
    Connect,
    ConnectResult,
}
impl TryFrom<u8> for EthanCommandType {
    type Error = anyhow::Error;
    fn try_from(value: u8) -> Result<Self, Self::Error> {
        match value {
            0x01 => Ok(Self::Auth),
            0x02 => Ok(Self::Trans),
            0x11 => Ok(Self::AuthResult),
            0x12 => Ok(Self::TransResponse),
            0x03 => Ok(Self::Connect),
            0x13 => Ok(Self::ConnectResult),
            _ => Err(anyhow!("not support value")),
        }
    }
}
impl From<EthanCommandType> for u8 {
    fn from(value: EthanCommandType) -> Self {
        match value {
            EthanCommandType::Auth => 0x01,
            EthanCommandType::Trans => 0x02,
            EthanCommandType::AuthResult => 0x11,
            EthanCommandType::TransResponse => 0x12,
            EthanCommandType::Connect => 0x03,
            EthanCommandType::ConnectResult => 0x13,
        }
    }
}

impl EthanRequestProto {
    pub fn new(cmd: EthanCommandType, data: Vec<u8>) -> Self {
        Self {
            cmd,
            len: data.len() as u16,
            data,
        }
    }
    pub fn read_from_bytes(bs: &mut BytesMut) -> Result<Self> {
        let cmd = bs.get_u8();
        let cmd = EthanCommandType::try_from(cmd)?;
        let len = bs.get_u16();
        let content = bs.split_to(len as usize);
        let data = content.to_vec();
        Ok(Self { cmd, len, data })
    }
    pub fn auth_data(&self) -> &[u8] {
        &self.data
    }
    pub fn data(&self) -> &[u8] {
        &self.data
    }
    pub fn cmd(&self) -> EthanCommandType {
        self.cmd
    }
    pub fn into_bytes(self) -> Vec<u8> {
        let mut res = vec![];
        res.put_u8(self.cmd.into());
        res.put_u16(self.len);
        res.extend(self.data);
        res
    }
}

#[derive(Debug, Clone, Copy)]
pub enum EthanAuthResult {
    Success,
    ServerError,
    IncorrectId,
}
impl TryFrom<u8> for EthanAuthResult {
    type Error = anyhow::Error;
    fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
        match value {
            0x01 => Ok(Self::Success),
            0x02 => Ok(Self::ServerError),
            0x03 => Ok(Self::IncorrectId),
            _ => Err(anyhow!("not support value")),
        }
    }
}
impl From<EthanAuthResult> for u8 {
    fn from(value: EthanAuthResult) -> Self {
        match value {
            EthanAuthResult::Success => 0x01,
            EthanAuthResult::ServerError => 0x02,
            EthanAuthResult::IncorrectId => 0x03,
        }
    }
}


///服务器连接结果
#[derive(Debug,Clone,Copy)]
pub enum EthanConnectResult{
    Success,
    ServerError,
    CannotAccess
}

impl TryFrom<u8> for EthanConnectResult{
    type Error = anyhow::Error;
    fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
        match value{
            0x01=>Ok(Self::Success),
            0x02=>Ok(Self::ServerError),
            0x03=>Ok(Self::CannotAccess),
            _=>Err(anyhow!("Not support value:{}",value))
        }
    }
}
impl Into<u8> for EthanConnectResult{
    fn into(self) -> u8 {
        match self{
            EthanConnectResult::Success => 0x01,
            EthanConnectResult::ServerError => 0x02,
            EthanConnectResult::CannotAccess => 0x03,
        }
    }
}